#include "rwxml.h"
using namespace std;


RwXml::RwXml()
{
    m_pDoc = nullptr;
}

RwXml::RwXml(const char *xmlpath)
{
    m_pDoc = readDoc(xmlpath);
}

RwXml::~RwXml()
{
    if(m_pDoc != NULL)
    {
        delete m_pDoc;
    }
}

TiXmlDocument* RwXml::readDoc(const char *xmlpath)
{
    TiXmlDocument *pDoc = new TiXmlDocument(xmlpath);
    if(NULL == pDoc)
    {
        cout<<"xml is NULL"<<endl;
        return NULL;
    }

    if(!pDoc->LoadFile())
    {
        cout<<"read failed!"<<endl;
        delete pDoc;
        return NULL;
    }

    return pDoc;
}

TiXmlNode* RwXml::selectChildNode(TiXmlNode *pNode, string nodeName)
{
    if(pNode == NULL)
    {
        return NULL;
    }

    TiXmlNode * pSelectedNode = NULL;
    TiXmlNode * pChildNode = NULL;
    int t = pNode->Type();
    switch (t)
    {
    case TiXmlText::TINYXML_DOCUMENT:
    case TiXmlText::TINYXML_DECLARATION:
    case TiXmlText::TINYXML_TEXT:
    case TiXmlText::TINYXML_UNKNOWN:
    case TiXmlText::TINYXML_COMMENT:
        break;
    case TiXmlText::TINYXML_ELEMENT:
        if(pNode->Value() == nodeName)
        {


            return pNode;


        }
        else
        {
            //循环访问它的每一个元素
            for(pChildNode=pNode->FirstChild();
                pChildNode!=0;
                pChildNode = pChildNode->NextSibling())
            {
                pSelectedNode = selectChildNode(
                            pChildNode,
                            nodeName);
                if(pSelectedNode)
                {
                    return pSelectedNode;
                }
            }
        }

    default:
        break;
    }

    return NULL;
}

TiXmlNode* RwXml::selectChildNode(TiXmlNode *pNode,string nodeName,string nodeAttrName,string nodeAttrValue)
{
    if(pNode == NULL)
    {
        return NULL;
    }
    TiXmlNode * pSelectedNode = NULL;
    TiXmlNode * pChildNode = NULL;
    int t = pNode->Type();
    switch (t)
    {
    case TiXmlText::TINYXML_DOCUMENT:
    case TiXmlText::TINYXML_DECLARATION:
    case TiXmlText::TINYXML_TEXT:
    case TiXmlText::TINYXML_UNKNOWN:
    case TiXmlText::TINYXML_COMMENT:
        break;

    case TiXmlText::TINYXML_ELEMENT:

        if(pNode->Value() == nodeName)
        {
            if(!nodeAttrName.empty())
            {
                TiXmlElement * pElement = pNode->ToElement();

                TiXmlAttribute * pAttr = pElement->FirstAttribute();
                do
                {
                    if(pAttr->Name()==nodeAttrName&&pAttr->Value()== nodeAttrValue)
                    {
                        return pNode;
                    }
                }while(pAttr = pAttr->Next());

            }
            else
            {
                return pNode;
            }
        }
        else
        {
            //循环访问它的每一个元素
            for(pChildNode=pNode->FirstChild();
                pChildNode!=0;
                pChildNode = pChildNode->NextSibling())
            {
                pSelectedNode = selectChildNode(pChildNode, nodeName, nodeAttrName, nodeAttrValue);
                if(pSelectedNode)
                {
                    return pSelectedNode;
                }
            }
        }

    default:
        break;
    }

    return NULL;
}

TiXmlDocument *RwXml::getDoc() const
{
    return m_pDoc;
}

TiXmlNode* RwXml::selectSingleNode(string nodeName,string nodeAttrName,string nodeAttrValue)
{
    TiXmlElement *pRootElement = m_pDoc->RootElement();
    if(pRootElement == NULL)
    {
        cout << "Parsing error can't get root" << endl;
        return NULL;
    }

    TiXmlNode *pNode  = NULL;
    TiXmlNode *pSelectNode = NULL;
    string msg = "";

    for(pNode=pRootElement->FirstChildElement();pNode;pNode=pNode->NextSiblingElement())
    {

        pSelectNode = selectChildNode(pNode,nodeName,nodeAttrName,nodeAttrValue);
        if(pSelectNode)
        {
            break;
        }
    }

    if(pSelectNode)
    {
        //cout << "Successful analysis" << endl;
        //cout << "[Node Name]=" << pSelectNode->Value() << endl;

        //char *pName = "NULL";
        //if(pSelectNode->ToElement() != nullptr &&  pSelectNode->ToElement()->Attribute("Name") != nullptr)
        //{
        //    pName = (char *)(pSelectNode->ToElement()->Attribute("Name"));
        //}

        //cout << "[attr]="<< pName <<endl;

        return pSelectNode;
    }
    else
    {
        //cout << "Parsing error, unable to get node " << nodeName.c_str() << endl;
        return NULL;
    }
}

TiXmlNode* RwXml::selectSingleNode(string nodeName)
{
    TiXmlElement *RootElement = m_pDoc->RootElement();
    if(RootElement == NULL)
    {
        cout << "Parsing error can't get root" << endl;
        return NULL;
    }

    TiXmlNode * pNode  = NULL;
    TiXmlNode * pSelectNode = NULL;
    string msg = "";

    for(pNode=RootElement->FirstChildElement();pNode;pNode=pNode->NextSiblingElement())
    {

        pSelectNode = selectChildNode(pNode,nodeName);
        if(pSelectNode)
        {
            break;
        }
    }

    if(pSelectNode)
    {
        //cout << "Successful analysis" << endl;
        //cout << "[Node Name]=" << pSelectNode->Value() << endl;

        //char *pName = "NULL";
        //if(pSelectNode->ToElement() != nullptr &&  pSelectNode->ToElement()->Attribute("Name") != nullptr)
        //{
        //    pName = (char *)(pSelectNode->ToElement()->Attribute("Name"));
        //}

        //cout << "[attr]="<< pName <<endl;

        return pSelectNode;
    }
    else
    {
        //cout << "Parsing error, unable to get node " << nodeName.c_str() << endl;
        return NULL;
    }
}

TiXmlNode* RwXml::selectSingleNode(string nodeName,TiXmlNode *parentNode)
{

    if(parentNode == NULL)
    {
        cout << "Parsing error can't get root" << endl;
        return NULL;
    }

    TiXmlNode * pNode  = NULL;
    TiXmlNode * pSelectNode = NULL;
    string msg = "";

    for(pNode=parentNode->FirstChildElement();pNode;pNode=pNode->NextSiblingElement())
    {

        pSelectNode = selectChildNode(pNode,nodeName);
        if(pSelectNode)
        {
            break;
        }
    }

    if(pSelectNode)
    {
        //cout << "Successful analysis" << endl;
        //cout << "[Node Name]=" << pSelectNode->Value() << endl;

        //char *pName = "NULL";
        //if(pSelectNode->ToElement() != nullptr &&  pSelectNode->ToElement()->Attribute("Name") != nullptr)
        //{
        //    pName = (char *)(pSelectNode->ToElement()->Attribute("Name"));
        //}

        //cout << "[attr]="<< pName <<endl;

        return pSelectNode;
    }
    else
    {
        //cout << "Parsing error, unable to get node " << nodeName.c_str() <<endl;
        return NULL;
    }
}

bool RwXml::addSingleNode(TiXmlNode *tNode, const char* nodeName, std::map<const char*, const char*> attrmap)
{
    //获得xml的头，即声明部分
    TiXmlDeclaration* decl = m_pDoc->FirstChild()->ToDeclaration();
    if(decl != NULL)
    {
        cout << "xml version:" << decl->Version()  << endl;
        cout << "xml Format encoding:" << decl->Encoding() << endl;
    }

    //获得根元素
    TiXmlElement *RootElement = m_pDoc->RootElement();
    if(RootElement != NULL)
    {

        TiXmlElement *pNewElement = new TiXmlElement(nodeName);
        tNode->LinkEndChild(pNewElement);
//        pNewElement->SetAttribute("iter.first","iter.second");
        for(auto &iter : attrmap)
        {
            pNewElement->SetAttribute(iter.first, iter.second);
        }
//        bool b = doc->SaveFile();
////        Doc->Print();
//        if(b)
//        {
//            cout << "Added successfully" << endl;
//            return b;
//        }
//        else
//        {
//            cout << "add failed" << endl;
//            return false;
//        }
//    }
        return true;
    }
    else
    {
        return false;
    }
}

bool RwXml::addSingleNode(TiXmlNode *tNode,const char* nodeName, std::map<string, string> attrmap)
{
    //获得xml的头，即声明部分
    TiXmlDeclaration* decl = m_pDoc->FirstChild()->ToDeclaration();
    if(decl != NULL)
    {
        cout << "xml version:" << decl->Version()  << endl;
        cout << "xml Format encoding:" << decl->Encoding() << endl;
    }
    //获得根元素
    TiXmlElement *RootElement = m_pDoc->RootElement();
    if(RootElement != NULL)
    {

        TiXmlElement *pNewElement = new TiXmlElement(nodeName);
        tNode->LinkEndChild(pNewElement);
//        pNewElement->SetAttribute("iter.first","iter.second");
        for(auto &iter : attrmap)
        {
            pNewElement->SetAttribute(iter.first.c_str(), iter.second.c_str());
        }
//        bool b = doc->SaveFile();
////        Doc->Print();
//        if(b)
//        {
//            cout << "Added successfully" << endl;
//            return b;
//        }
//        else
//        {
//            cout << "add failed" << endl;
//            return false;
//        }
//    }
        return true;
    }
    else
    {
        return false;
    }
}


TiXmlNode *RwXml::addSingleNodeAndReturn(TiXmlNode *tNode, const char *nodeName, std::map<const char *, const char *> attrmap)
{
    TiXmlDeclaration* decl = m_pDoc->FirstChild()->ToDeclaration();
    if(decl != NULL)
    {
        cout << "xml version:" << decl->Version()  << endl;
        cout << "xml Format encoding:" << decl->Encoding() << endl;
    }

    //获得根元素
    TiXmlElement *pRootElement = m_pDoc->RootElement();
    if(pRootElement != NULL)
    {

        TiXmlElement *pNewElement = new TiXmlElement(nodeName);
        tNode->LinkEndChild(pNewElement);
//        pNewElement->SetAttribute("iter.first","iter.second");
        for(auto &iter : attrmap)
        {
            pNewElement->SetAttribute(iter.first,iter.second);
        }
        return pNewElement;
//        bool b = doc->SaveFile();
////        Doc->Print();
//        if(b)
//        {
//            cout << "Added successfully" << endl;
//            return pNewElement;
//        }
//        else
//        {
//            cout << "add failed" << endl;
//            return NULL;
//        }
    }
    else
    {
        return NULL;
    }
}

TiXmlNode *RwXml::addSingleNodeAndReturn(TiXmlNode *tNode, string strNodeName, std::map<string, string> attrmap)
{
    if(nullptr != m_pDoc->RootElement())
    {
        TiXmlElement *pNewElement = new TiXmlElement(strNodeName.c_str());
        tNode->LinkEndChild(pNewElement);

        for(auto &iter : attrmap)
        {
            pNewElement->SetAttribute(iter.first.c_str(), iter.second.c_str());
        }

        return pNewElement;
    }
    else
    {
        return nullptr;
    }
}

bool RwXml::addNoAttrNode(TiXmlNode *tNode,const char* nodeName)
{
    //获得根元素
    TiXmlElement *pRootElement = m_pDoc->RootElement();
    if(pRootElement != NULL)
    {
        TiXmlElement *pNewElement = new TiXmlElement(nodeName);
        tNode->LinkEndChild(pNewElement);
        return true;
    }
    else
    {
        return false;
    }
}

void RwXml::addNoAttrNode(TiXmlNode* &tNode, TiXmlElement* &cNode)
{
    TiXmlElement *pRootElement = m_pDoc->RootElement();
    if(pRootElement != nullptr)
    {
        tNode->LinkEndChild(cNode);
    }
}

TiXmlNode* RwXml::addNoAttrNodeAndReturn(TiXmlNode *tNode, const char *nodeName)
{
    TiXmlElement *pRootElement = m_pDoc->RootElement();
    if(pRootElement != NULL)
    {
        TiXmlElement *pNewElement = new TiXmlElement(nodeName);
        tNode->LinkEndChild(pNewElement);
        return pNewElement;
    }
}

bool RwXml::delSingleNode(TiXmlNode *pNode)
{
    TiXmlElement *pRootElement = m_pDoc->RootElement();
    if(pRootElement != NULL)
    {
        if (pRootElement == pNode)
        {
              if(m_pDoc->RemoveChild(pRootElement))
              {
                   m_pDoc->SaveFile();
                   cout<<"Del root success"<<endl;
                   return true;
              }
              else
              {
                  return false;
              }
        }

        if (NULL != pNode)
        {
            TiXmlNode* pParentNode = pNode->Parent();
            if (NULL == pParentNode)
            {
                 cout<<"Parent Node is NULL"<<endl;
            }

            if(NULL != pParentNode)
            {
                if(pParentNode->RemoveChild(pNode))
                {
                    cout<<"read node sucess"<<endl;
                    return true;
                }
                else
                {
                    cout<<"Del false"<<endl;
                    return false;
                }
           }
        }
        else
        {
            return false;
        }
    }
}

vector<TiXmlNode*> RwXml::getNodeVec(const char* nodeName)
{
    if(nullptr == m_pDoc)
    {
        return vector<TiXmlNode*>();
    }

    //获得根元素
    TiXmlElement *pRootElement = m_pDoc->RootElement();

    vector<TiXmlNode *> nodeVec;
    TiXmlNode* pNode  = NULL;

    for(pNode = pRootElement->FirstChildElement(); pNode; pNode = pNode->NextSiblingElement())
    {
        insertNodeVec(pNode, nodeName, nodeVec);
    }

    return nodeVec;
}

vector<TiXmlNode*> RwXml::getSelectNodeVec(const char* nodeName, TiXmlNode* selectNode)
{
    if(nullptr == nodeName || nullptr == selectNode)
    {
        return vector<TiXmlNode*>();
    }

    vector<TiXmlNode*> nodeVec;
    TiXmlNode* pNode  = NULL;

    for(pNode=selectNode->FirstChildElement();pNode;pNode=pNode->NextSiblingElement())
    {
        insertNodeVec(pNode,nodeName,nodeVec);
    }

    return nodeVec;
}

TiXmlNode *RwXml::changeNodeAttr(TiXmlNode *pNode, string attrName, string attrValue)
{
    TiXmlAttribute* pAttr = NULL;
    for (pAttr = pNode->ToElement()->FirstAttribute(); pAttr; pAttr = pAttr->Next())
    {
      if(pAttr->Name() == attrName.c_str())
      {
          pAttr->SetValue(attrValue.c_str());
      }
    }

    return pNode;
}

TiXmlElement *RwXml::getRootElement()
{
    TiXmlElement *proot_element;
    proot_element = m_pDoc->RootElement();
    return proot_element;
}

void RwXml::saveDom()
{
    m_pDoc->SaveFile();
}

void RwXml::saveDom(const char *path)
{
     m_pDoc->SaveFile(path);
}

void RwXml::setDoc(TiXmlDocument *Doc)
{
    m_pDoc = Doc;
}

std::vector<TiXmlNode*> RwXml::getNodeVec(const char *nodeName, TiXmlNode *parentNode)
{
    if(nullptr == nodeName || nullptr == parentNode)
    {
        return std::vector<TiXmlNode*>();
    }

    vector<TiXmlNode*> nodeVec;
    TiXmlNode* pNode  = NULL;

    for(pNode=parentNode->FirstChildElement(); pNode != nullptr; pNode=pNode->NextSiblingElement())
    {
        insertNodeVec(pNode,nodeName,nodeVec);
    }

    return nodeVec;
}

void  RwXml::insertNodeVec(TiXmlNode * pNode,const char* nodeName,vector<TiXmlNode*> &nodeVec)
{
    if(pNode == NULL)
    {
        cout<<"node is null"<<endl;
    }

    TiXmlNode* pChildNode = NULL;
    int t = pNode->Type();
    switch(t)
    {
        //节点类型是Element
        case TiXmlText::TINYXML_ELEMENT:
        {
            if(0 == strcmp(nodeName, pNode->Value()))
            {

                nodeVec.push_back(pNode);

            }

            for(pChildNode=pNode->FirstChild();pChildNode!=0;pChildNode = pChildNode->NextSibling())
            {
                insertNodeVec(pChildNode,nodeName,nodeVec);
            }

            break;
        }

        case TiXmlText::TINYXML_DOCUMENT:
        case TiXmlText::TINYXML_COMMENT:
        case TiXmlText::TINYXML_UNKNOWN:
        case TiXmlText::TINYXML_DECLARATION:
        case TiXmlText::TINYXML_TYPECOUNT:
        {
            break; //Nothing to do
        }
    }
}
